package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.common.exception.StgyException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.model.entity.*;
import com.atguigu.lease.model.enums.ItemType;
import com.atguigu.lease.model.enums.ReleaseStatus;
import com.atguigu.lease.web.admin.mapper.*;
import com.atguigu.lease.web.admin.service.*;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentDetailVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentItemVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentQueryDto;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentSubmitDto;
import com.atguigu.lease.web.admin.vo.fee.FeeValueVo;
import com.atguigu.lease.web.admin.vo.graph.GraphVo;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author gqs
 * @description 针对表【apartment_info(公寓信息表)】的数据库操作Service实现
 * @createDate 2023-07-24 15:48:00
 */
@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo>
    implements ApartmentInfoService {
  @Autowired private ApartmentFacilityMapper apartmentFacilityMapper;
  @Autowired private ApartmentLabelMapper apartmentLabelMapper;
  @Autowired private ApartmentFeeValueMapper apartmentFeeValueMapper;
  @Autowired private GraphInfoMapper graphInfoMapper;
  @Autowired private ApartmentInfoMapper apartmentInfoMapper;
  @Autowired private DistrictInfoMapper districtInfoMapper;

  @Autowired private ApartmentFacilityService apartmentFacilityService;
  @Autowired private ApartmentLabelService apartmentLabelService;
  @Autowired private ApartmentFeeValueService apartmentFeeValueService;
  @Autowired private GraphInfoService graphInfoService;
  @Autowired private FileService fileService;

  @Override
  @Transactional(rollbackFor = Exception.class) // 添加事务
  public boolean saveOrUpdateApartmentInfo(ApartmentSubmitDto apartmentSubmitDto) {
    // 1.公寓信息添加唯一性校验
    Long apartmentId =
        apartmentSubmitDto.getId() == null ? -1L : apartmentSubmitDto.getId(); // -1 表示新增 否则是更新
    // 同一个区域不能有重名的公寓名称
    ApartmentInfo dbApartmentInfo =
        this.getOne(
            Wrappers.lambdaQuery(ApartmentInfo.class)
                .eq(ApartmentInfo::getName, apartmentSubmitDto.getName())
                .eq(ApartmentInfo::getDistrictId, apartmentSubmitDto.getDistrictId())
                .last("limit 1"));
    if (dbApartmentInfo != null && !dbApartmentInfo.getId().equals(apartmentId)) {
      // 公寓名称重复 返回错误信息
      throw new StgyException(ResultCodeEnum.APARTMENT_INFO_EXISTS_ERROR);
    }
    // 2.根据apartmentId判断是更新还是新增
    if (!apartmentId.equals(-1L)) {
      // 更新时 先删除所有的一对多映射关系信息 中间表信息可以采用物理删除
      // apartment_facility: 公寓id映射配套id 根据公寓id删除它的所有配套
      apartmentFacilityMapper.deleteByApartmentInfoId(apartmentId);
      // apartment_label
      apartmentLabelMapper.deleteByApartmentInfoId(apartmentId);
      // apartment_fee_value
      apartmentFeeValueMapper.deleteByApartmentInfoId(apartmentId);
      // graph_info:
      graphInfoMapper.deleteByApartmentInfoId(apartmentId);
    }
    // 3.保存或更新公寓信息apartmentInfo
    ApartmentInfo apartmentInfo = new ApartmentInfo();
    BeanUtils.copyProperties(apartmentSubmitDto, apartmentInfo);
    // 根据省市区id查询公寓的省市区名称并插入
    Map<String, String> namesMap =
        districtInfoMapper.selectNamesByDid(apartmentSubmitDto.getDistrictId());
    apartmentInfo.setDistrictName(namesMap.get("dName"));
    apartmentInfo.setCityName(namesMap.get("cName"));
    apartmentInfo.setProvinceName(namesMap.get("pName"));
    this.saveOrUpdate(apartmentInfo);
    // 4.添加apartment_facility: 公寓id映射配套id
    // 公寓配套id集合
    List<Long> facilityInfoIds = apartmentSubmitDto.getFacilityInfoIds();
    if (!CollectionUtils.isEmpty(facilityInfoIds)) {
      // 如果集合不为空
      List<ApartmentFacility> facilityList = new ArrayList<>();
      for (Long facilityInfoId : facilityInfoIds) {
        ApartmentFacility apartmentFacility = new ApartmentFacility();
        apartmentFacility.setApartmentId(apartmentSubmitDto.getId());
        apartmentFacility.setFacilityId(facilityInfoId);
        // 添加到集合中
        facilityList.add(apartmentFacility);
      }
      apartmentFacilityService.saveBatch(facilityList);
    }
    // 5.添加apartment_label: 公寓id映射标签id
    List<Long> labelIds = apartmentSubmitDto.getLabelIds();
    if (!CollectionUtils.isEmpty(labelIds)) {
      // 如果集合不为空
      List<ApartmentLabel> apartmentLabelList = new ArrayList<>();
      for (Long labelId : labelIds) {
        ApartmentLabel apartmentLabel = new ApartmentLabel();
        apartmentLabel.setApartmentId(apartmentSubmitDto.getId());
        apartmentLabel.setLabelId(labelId);
        // 添加到集合中
        apartmentLabelList.add(apartmentLabel);
      }
      apartmentLabelService.saveBatch(apartmentLabelList);
    }
    // 6.添加apartment_fee_value: 公寓id映射杂费值id
    List<Long> feeValueIds = apartmentSubmitDto.getFeeValueIds();
    if (!CollectionUtils.isEmpty(feeValueIds)) {
      List<ApartmentFeeValue> apartmentFeeValueList = new ArrayList<>();
      for (Long feeValueId : feeValueIds) {
        ApartmentFeeValue apartmentFeeValue = new ApartmentFeeValue();
        apartmentFeeValue.setApartmentId(apartmentSubmitDto.getId());
        apartmentFeeValue.setFeeValueId(feeValueId);
        // 添加到集合中
        apartmentFeeValueList.add(apartmentFeeValue);
      }
      apartmentFeeValueService.saveBatch(apartmentFeeValueList);
    }
    // 7.graph_info: 公寓id映射图片id
    List<GraphVo> graphVoList = apartmentSubmitDto.getGraphVoList();
    if (!CollectionUtils.isEmpty(graphVoList)) {
      ArrayList<GraphInfo> graphInfoList = new ArrayList<>();
      for (GraphVo graphVo : graphVoList) {
        GraphInfo graphInfo = new GraphInfo();
        graphInfo.setItemType(ItemType.APARTMENT);
        graphInfo.setItemId(apartmentSubmitDto.getId());
        graphInfo.setName(graphVo.getName());
        graphInfo.setUrl(graphVo.getUrl());
        graphInfoList.add(graphInfo);
      }
      graphInfoService.saveBatch(graphInfoList);
    }

    return true;
  }

  @Override
  public IPage<ApartmentItemVo> pageApartmentItemByQuery(
      IPage<ApartmentItemVo> page, ApartmentQueryDto queryVo) {
    return apartmentInfoMapper.pageApartmentItemByQueryMapper(page, queryVo);
  }

  @Override
  public ApartmentDetailVo getApartmentDetailById(Long id) {
    // 1.查询ApartmentInfo
    ApartmentInfo apartmentInfo = this.getById(id);
    if (apartmentInfo == null) {
      throw new StgyException(ResultCodeEnum.DATA_ERROR);
    }

    // 2. 查询GraphInfo
    List<GraphVo> graphVoList =
        graphInfoMapper.selectGraphVoListByItemTypeAndId(ItemType.APARTMENT, id);
    // 3.查询LabelInfo
    List<LabelInfo> labelInfoList = apartmentLabelMapper.selectLabelInfosByApartmentId(id);
    // 4.查询FacilityInfo
    List<FacilityInfo> facilityInfoList =
        apartmentFacilityMapper.selectFacilityInfosByApartmentId(id);
    // 5.查询FeeValue
    List<FeeValueVo> feeValueVoList = apartmentFeeValueMapper.selectFeeValueVosByApartmentId(id);

    // 装配数据
    ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();

    BeanUtils.copyProperties(apartmentInfo, apartmentDetailVo);
    // List<GraphVo> graphVoList = new ArrayList<>();
    // BeanUtils.copyProperties(graphInfoList,graphVoList);
    apartmentDetailVo.setGraphVoList(graphVoList);
    apartmentDetailVo.setLabelInfoList(labelInfoList);
    apartmentDetailVo.setFacilityInfoList(facilityInfoList);
    apartmentDetailVo.setFeeValueVoList(feeValueVoList);

    return apartmentDetailVo;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean removeApartmentById(Long id) {
    // 删除apartmentInfo 逻辑删除
    this.removeById(id);
    // 中间表信息物理删除
    // 1.删除GraphInfo
    graphInfoMapper.deleteByApartmentInfoId(id);
    // 根据公寓id和枚举类型删除minio中的图片
    List<GraphInfo> UrlList =
        graphInfoService.list(
            Wrappers.lambdaQuery(GraphInfo.class)
                .eq(GraphInfo::getItemType, ItemType.APARTMENT)
                .eq(GraphInfo::getItemId, id));
    for (GraphInfo graphInfo : UrlList) {
      fileService.delete(graphInfo.getUrl());
    }
    // 3.删除ApartmentFacility
    apartmentFacilityMapper.deleteByApartmentInfoId(id);
    // 2.删除ApartmentLabel
    apartmentLabelMapper.deleteByApartmentInfoId(id);
    // 4.删除ApartmentFeeValue
    apartmentFeeValueMapper.deleteByApartmentInfoId(id);
    return true;
  }

  @Override
  public boolean updateReleaseStatusById(Long id, ReleaseStatus status) {
    boolean flag =
        this.update(
            new LambdaUpdateWrapper<ApartmentInfo>()
                .eq(ApartmentInfo::getId, id)
                .set(ApartmentInfo::getIsRelease, status));
    return flag;
  }

  @Override
  public List<ApartmentInfo> listInfoByDistrictId(Long id) {
    List<ApartmentInfo> list =
        this.list(Wrappers.lambdaQuery(ApartmentInfo.class).eq(ApartmentInfo::getDistrictId, id));
    if (CollectionUtils.isEmpty(list)) {
      return null;
    }
    return list;
  }
}
